export class requestHeader {
  accessKey: string;
  static readonly dalvik_ver = "2.1.0";
  static readonly os_ver = "9";
  static readonly brand = "Xiaomi";
  static readonly model = "MIUI";
  static readonly app_ver = "6.7.0";
  static readonly build = 6070600;
  static readonly channel = "bilibili140";
  static readonly network_type = 1;
  static readonly network_tf = 0;
  static readonly network_oid = "46007";
  static readonly cronet = "1.21.0";
  static readonly buvid = "XZFD48CFF1E68E637D0DF11A562468A8DC314";
  static readonly mobiApp = "android";
  static readonly platform = "android";
  static readonly env = "prod";
  static readonly appId = 1;
  static readonly region = "CN";
  static readonly language = "zh";

  constructor(accessKey: string) {
    this.accessKey = accessKey;
  }

  getFawkesreqBin(): string {
    const msg = {
      Appkey: requestHeader.mobiApp,
      Env: requestHeader.env
    };
    return this.toBase64(this.toArrayBuffer(msg));
  }

  getMetadataBin(): string {
    const msg = {
      AccessKey: this.accessKey,
      MobiApp: requestHeader.mobiApp,
      Build: requestHeader.build,
      Channel: requestHeader.channel,
      Buvid: requestHeader.buvid,
      Platform: requestHeader.platform
    };
    return this.toBase64(this.toArrayBuffer(msg));
  }

  getDeviceBin(): string {
    const msg = {
      AppId: requestHeader.appId,
      MobiApp: requestHeader.mobiApp,
      Build: requestHeader.build,
      Channel: requestHeader.channel,
      Buvid: requestHeader.buvid,
      Platform: requestHeader.platform,
      Brand: requestHeader.brand,
      Model: requestHeader.model,
      Osver: requestHeader.os_ver
    };
    return this.toBase64(this.toArrayBuffer(msg));
  }

  getNetworkBin(): string {
    const msg = {
      Type: "Wifi",
      Oid: requestHeader.network_oid
    };
    return this.toBase64(this.toArrayBuffer(msg));
  }

  getRestrictionBin(): string {
    const msg = {};
    return this.toBase64(this.toArrayBuffer(msg));
  }

  getLocaleBin(): string {
    const msg = {
      CLocale: {
        Language: requestHeader.language,
        Region: requestHeader.region
      },
      SLocale: {
        Language: requestHeader.language,
        Region: requestHeader.region
      }
    };
    return this.toBase64(this.toArrayBuffer(msg));
  }

  toBase64(data: ArrayBuffer): string {
    const bytes = new Uint8Array(data);
    let base64 = "";
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    let padding = 0;
    const length = bytes.length;
    for (let i = 0; i < length; i += 3) {
      const b1 = bytes[i];
      const b2 = i + 1 < length ? bytes[i + 1] : 0;
      const b3 = i + 2 < length ? bytes[i + 2] : 0;
      const triplet = (b1 << 16) | (b2 << 8) | b3;
      const index1 = (triplet >> 18) & 63;
      const index2 = (triplet >> 12) & 63;
      const index3 = (triplet >> 6) & 63;
      const index4 = triplet & 63;
      base64 += chars[index1] + chars[index2] + chars[index3] + chars[index4];
      if (i + 2 >= length)
        padding = i + 2 - length + 1;
    }
    return base64.slice(0, base64.length - padding) + "=".repeat(padding);
  }

  toArrayBuffer(obj: object): ArrayBuffer {
    const jsonString = JSON.stringify(obj);
    const data = new Uint8Array(jsonString.length);
    for (let i = 0; i < jsonString.length; ++i)
      data[i] = jsonString.charCodeAt(i);
    return data.buffer;
  }
}